﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace y12fjydbs_1
{
    public class MySerialPort
    { 
        private static SerialPort cSerialPort;
        public static string cComName;
        public static int cBand;
        private readonly object cMux;
        private int cSendCount = 0;
        private int cReceiveCount = 0;
        private readonly ConcurrentQueue<byte[]> cMessageQueue;
        private readonly EventWaitHandle cMessageWaitHandle;

        public MySerialPort()
        { 
            if(string.IsNullOrWhiteSpace( cComName))
            {
                cComName = "COM12";
            }
            if (cBand <= 0)
                cBand = 9600;

            cMux = new object();
            cReceiveCount = 0;
            cMessageQueue = new ConcurrentQueue<byte[]>();
            cMessageWaitHandle = new EventWaitHandle(false, EventResetMode.AutoReset);

            OpenCom();

            ReceiveMsg();
        }

        private void OpenCom()
        {
            cSerialPort = new SerialPort(cComName, cBand);
            if (cSerialPort.IsOpen)
                cSerialPort.Close();
            cSerialPort.ReadTimeout = 500;
            cSerialPort.WriteTimeout = 500;

            cSerialPort.ReadBufferSize = 1024;
            cSerialPort.WriteBufferSize = 1024;

            cSerialPort.Open();
            Msg.WriteLine($"串口 [ {cComName} ] 已打开!");

            cSerialPort.DiscardInBuffer();
            cSerialPort.DiscardOutBuffer();
        }

        #region 接受数据
        public void ReceiveMsg()
        {
            cSerialPort.DataReceived += (sender, e) =>
            {
                lock(cMux)
                {
                    if (cSerialPort.IsOpen == false)
                        return;
                    int len = cSerialPort.BytesToRead;
                    byte[] buff = new byte[len];
                    cSerialPort.Read(buff, 0, len);
                    cReceiveCount += len;
                    cMessageQueue.Enqueue(buff);
                    cMessageWaitHandle.Set();
                    Thread.Sleep(100);
                }
            };
        }
        #endregion

        #region 获取串口收到的数据
        public byte[] TryMessage(int msToTimeout = -1)
        {
            if (cMessageQueue.TryDequeue(out var message))
            {
                return message;
            }

            if (cMessageWaitHandle.WaitOne(msToTimeout))
            {
                if(cMessageQueue.TryDequeue(out message))
                {
                    return message;
                }
            }
            return default;
        }
        #endregion


        #region 发送消息
        public void Send(byte[] buff)
        {
            lock(cMux)
            {
                Msg.WriteLine("---------------->>> " + BitConverter.ToString(buff));
                cSerialPort.Write(buff, 0, buff.Length);
                cSendCount += buff.Length;
            }
        }
        #endregion

        #region 清空发送接受总数统计
        public void ClearCount()
        {
            lock (cMux)
            {
                cSendCount = 0;
                cReceiveCount = 0;
            }
        }
        #endregion

        #region 关闭串口
        public void Close()
        {
            cSerialPort.Close();
        }
        #endregion
    }
}
